from classfile.class_reader import ClassReader


class ClassFile:
    def __init__(self):
        from classfile.constant_pool import ConstantPool
        self.magic = None
        self.minorVersion = 0
        self.majorVersion = 0
        self.constantPool = ConstantPool()
        self.accessFlags = 0
        self.thisClass = None
        self.superClass = None
        self.interfaces = None
        self.fields = None
        self.methods = None
        self.attributes = ()

    def read(self, clsReader):
        from classfile.member_info import MemberInfo
        from classfile.attribute_info import AttributeInfo
        self.readAndCheckMagic(clsReader)
        self.readAndCheckVersion(clsReader)
        self.constantPool.readConstantPool(clsReader)
        self.accessFlags = clsReader.readU16()
        self.thisClass = int.from_bytes(clsReader.readU16(), "big")
        self.superClass = int.from_bytes(clsReader.readU16(), "big")
        self.interfaces = clsReader.readU16s()
        self.fields = MemberInfo.readMembers(clsReader, self.constantPool)
        self.methods = MemberInfo.readMembers(clsReader, self.constantPool)
        self.attributes = AttributeInfo.readAttributes(clsReader, self.constantPool)

    def readAndCheckMagic(self, clsReader: ClassReader):
        self.magic = clsReader.readU32()

    def readAndCheckVersion(self, clsReader: ClassReader):
        self.minorVersion = clsReader.readU16()
        self.majorVersion = clsReader.readU16()

    @property
    def className(self):
        return self.constantPool.getClassName(self.thisClass)

    @property
    def superClassName(self):
        return self.constantPool.getClassName(self.superClass)

    @property
    def interfaceNames(self):
        names = []
        for interface in self.interfaces:
            names.append(self.constantPool.getClassName(int.from_bytes(interface, "big")))
        return names

    @property
    def sourceFileAttribute(self):
        from classfile.attribute_info import SOURCE_FILE
        for attr in self.attributes:
            if attr.type == SOURCE_FILE:
                return attr
        return None

    def getMinorVersion(self):
        return self.minorVersion

    def getMajorVersion(self):
        return self.majorVersion

    def getConstantPool(self):
        return self.constantPool

    def getAccessFlags(self):
        return self.accessFlags

    def getFields(self):
        return self.fields

    def getMethods(self):
        return self.methods

    @staticmethod
    def parse(clsData):
        clsReader = ClassReader(clsData)
        clsFile = ClassFile()
        clsFile.read(clsReader)
        return clsFile


if __name__ == '__main__':
    path = r"C:\Users\admin\Desktop\wrokspace\TestProject\target\classes\com\lm\local1\Test.class"
    with open(path, "rb") as f:
        clsFile = ClassFile.parse(f.read())
        print(clsFile)
